#!/bin/sh
# PCP QA Test No. 994
# Try to check permissions of package artifacts.
#
# With a single --fix option, is silent except if there is a problem
# and repairs any damage (this is used from check).
#
# See src/mkpermslist and src/permslist.
#
# Copyright (c) 2013 Ken McDonell.  All Rights Reserved.
#

fix=false
[ $# -eq 1 -a "$1" = "--fix" ] && fix=true

seq=`basename $0`
$fix || echo "QA output created by $seq"

# get standard environment, filters and checks
. ./common.product
. ./common.filter
. ./common.check

status=0	# success is the default!
$sudo rm -rf $tmp.* $seq.full
trap "cd $here; rm -rf $tmp.*; exit \$status" 0 1 2 3 15

_fixmode()
{
    if [ -L "$2" ]
    then
	: do nothing
    else
	$sudo chmod "$1" "$2"
    fi
    echo "Fixed."
}

_fixown()
{
    if [ -L "$2" ]
    then
	$sudo chown -h "$1" "$2"
    else
	$sudo chown "$1" "$2"
    fi
    echo "Fixed."
}

_fixgrp()
{
    if [ -L "$2" ]
    then
	$sudo chgrp -h "$1" "$2"
    else
	$sudo chgrp "$1" "$2"
    fi
    echo "Fixed."
}

if [ ! -f src/permslist ]
then
    echo "Arrgh .. src/permslist is missing.  Need to"
    echo "	$ cd src; ./mkpermslist"
    echo "in a git tree containg the PCP source and then try again."
    status=1
    exit
fi

root_group=root
case $PCP_PLATFORM
in
    freebsd|netbsd|openbsd|darwin)
	    root_group=wheel
	    ;;
esac

# real QA test starts here

line=0
# permslist format ...
# src/pmdas/mmv/GNUmakefile|1777|root|root|/var/tmp/mmv
# but also need to expand PCP env vars we expect to find
sed -e 's/ /\\ /g' -e 's/|/ /g' <src/permslist \
    -e 's@$(PCP_USER)@'$PCP_USER@g \
    -e 's@$(PCP_GROUP)@'$PCP_GROUP@g \
    -e 's@$(PCP_SA_DIR)@'$PCP_SA_DIR@g \
    -e 's@$(PCP_PMLOGGERCONTROL_PATH)@'$PCP_PMLOGGERCONTROL_PATH@g \
    -e 's@$(PCP_PMIECONTROL_PATH)@'$PCP_PMIECONTROL_PATH@g \
    -e 's@$(PCP_TMP_DIR)@'$PCP_TMP_DIR@g \
    -e 's@$(PCP_TMPFILE_DIR)@'$PCP_TMPFILE_DIR@g \
    -e 's@$(PCP_LOG_DIR)@'$PCP_LOG_DIR@g \
    -e 's@$(PCP_VAR_DIR)@'$PCP_VAR_DIR@g \
    -e 's@$(PCP_RUN_DIR)@'$PCP_RUN_DIR@g \
    -e 's@$(PCP_SECURE_DB_PATH)@'$PCP_SECURE_DB_PATH@g \
    -e 's@$(PCP_SHARE_DIR)@'$PCP_SHARE_DIR@g \
    -e 's@$(PCP_SYSCONF_DIR)@'$PCP_SYSCONF_DIR@g \
| tee -a $seq.full \
| while read makefile mode owner group target optional
do
    line=`expr $line + 1`
    if [ -z "$target" ]
    then
	if $fix
	then
	    : say nothing
	else
	    macro=`sed -n -e "${line}p" src/permslist | $PCP_AWK_PROG -F\| '{print $5}'`
	    echo "Warning: src/permslist: pcp.conf macro problem: $macro -> nothing"
	fi
	continue
    fi
    if [ ! -f "$target" -a ! -d "$target" ]
    then
	[ -z "$optional" ] && \
	    echo "Error: $target: not found, should have been installed from $makefile"
    elif [ "$target" = "/tmp" -o "$target" = "/var/tmp" ]
    then
	# when $PCP_TMPFILE_DIR is one of these, don't muck with it!
	#
	:
    else
	_mode=""
	_owner=""
	_group=""
	if [ $PCP_PLATFORM = linux -o $PCP_PLATFORM = solaris ]
	then
	    # stat line of interest ...
	    # Access: (1777/drwxrwxrwt)  Uid: (  0/  root)   Gid: (  0/  root)
	    #
	    eval `LC_ALL=C stat $target | sed -n -e '/^Access:.*Uid:.*Gid:/{
s/Access: *(/_mode=/
s/\/.*) *Uid: *( *[0-9][0-9]*\/ */ _owner=/
s/) *Gid: *( *[0-9][0-9]*\/ */ _group=/
s/).*//
s/=0*/=/g
p
}'`
	elif [ $PCP_PLATFORM = freebsd -o $PCP_PLATFORM = darwin -o $PCP_PLATFORM = netbsd -o $PCP_PLATFORM = openbsd ]
	then
	    # stat line of interest ... (mode is in bottom 4 octal digits,
	    # stripped of leading zeroes)
	    # _mode=100644 _user=kenj _group=kenj
	    # _mode=41777 _user=root _group=wheel
	    #
	    eval `stat -f '_mode=%Op _owner=%Su _group=%Sg' $target`
	    _mode=`echo $_mode | sed -e 's/.*\(....\)$/\1/' -e 's/^0*\(.\)/\1/'`
	else
	    echo "Arrgh, need stat(1) handling for $PCP_PLATFORM"
	    status=1
	    break
	fi
	if [ -z "$_mode" -o -z "$_owner" -o -z "$_group" ]
	then
	    echo "Arrgh, failed to extract mode, owner and group from stat(1) output ..."
	    stat $target
	    status=1
	    break
	fi
	[ "$group" = root ] && group="$root_group"
	#debug# echo "$target: mode: have $_mode expect $mode"
	#debug# echo "$target: owner: have $_owner expect $owner"
	#debug# echo "$target: group: have $_group expect $group"
	if [ "$_mode" != "$mode" ]
	then
	    echo "$target: wrong mode: expected $mode (from $makefile), found $_mode"
	    ls -ld $target
	    $fix && _fixmode "$mode" "$target"
	fi
	if [ "$_owner" != "$owner" ]
	then
	    echo "$target: wrong owner: expected $owner (from $makefile), found $_owner"
	    ls -ld $target
	    $fix && _fixown "$owner" "$target"

	fi
	if [ "$_group" != "$group" ]
	then
	    echo "$target: wrong group: expected $group (from $makefile), found $_group"
	    ls -ld $target
	    $fix && _fixgrp "$group" "$target"
	fi
    fi
done

# Now expect only root owned things below $PCP_SYSCONF_DIR,
# except for nssdb which has ownership $PCP_USER:$PCP_GROUP
# (pmproxy is both client and server and needs r/w access).
#
find $PCP_SYSCONF_DIR ! -user root | \
    grep -v "^$PCP_SECURE_DB_PATH" \
    > $tmp.out
if [ -s $tmp.out ]
then
    echo "Arrgh ... these files should be owned by root"
    cat $tmp.out | xargs ls -ld
    if $fix
    then
	cat $tmp.out \
	| while read file
	do
	    _fixown "root:$root_group" "$file"
	done
    fi
fi

# success, all done
status=0

exit
